Duplicate Functions

Took me 4 hours but finally figured it out. As per the code below, function "fA()" has duplicate parameters, one before function "B()" (print "1st") and one after (print "2nd"). B() calls fA(). The main program calls fA then B. The 2nd duplicate prints first, but then I get an exception at the call in B. I notice if I forward reference fA() before B() (at line 3) then it works fine, thye 2nd duplicate is always called. I could not get the first duplicate to run correctly.

For higher languages, is that normal?

  • Louie
void    fA()    {  print "In fA() 1st\n" }
 
// void fA(void)        // Forward Reference; Comment this line in and out
void    B()     {  fA() }
 
void    fA()    {   print "In fA() 2nd\n" 
}
//void fA(void) // Comment this line in and out
 
        // Call functions:
fA()
B()

llandale - Thu Jun 30 16:14:08 EDT 2011

Re: Duplicate Functions
Mathias Mamsch - Thu Jun 30 19:26:01 EDT 2011

That is not normal, but I noticed the same. A forward reference before and after the call will crash DOORS with an exception. I guess forward references are not properly implemented. If utterly needed, you could replace the forward declarations by a callback proxy like below. Nice thing about that is, you can change the function at runtime ...
 

// instead of forward declaring  func() use a virtual function 
int adFunc = 0; 
void call_func_proxy( void cb(int), int x ) { cb(x) }
void set_func (void cb(int) ) { adFunc = (addr_ cb) int }
void func (int x) { if (adFunc != 0) call_func_proxy(addr_ adFunc, x) }
 
// that function uses the not yet declared func() ...
void myLibraryFunction () { func 10 }
 
// declare the func we want to use late
void theRealFunc (int var) {
   print "This is the implementation of func that I would like to use:" var "\n"
}
// set it as the function we want to use now. May want to change that later. 
set_func(theRealFunc) 
 
myLibraryFunction ()

 


Regards, Mathias

 

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

 

Re: Duplicate Functions
SystemAdmin - Wed Jul 06 10:15:05 EDT 2011

Complied languages should either flag that as an error or print "2nd" both times, depending on how lenient they are about redefinitions. Interpreted languages should print "2nd" both times. I'm a burgeoning Ruby nerd in my off time, and the code below prints "2" both times.

#!/usr/bin/ruby1.9.1
 
def funcA
   puts("1")
end
 
def funcB
   funcA()
end
 
def funcA
   puts("2")
end
 
funcA()
funcB()

Re: Duplicate Functions
Mathias Mamsch - Thu Jul 07 03:35:56 EDT 2011

SystemAdmin - Wed Jul 06 10:15:05 EDT 2011

Complied languages should either flag that as an error or print "2nd" both times, depending on how lenient they are about redefinitions. Interpreted languages should print "2nd" both times. I'm a burgeoning Ruby nerd in my off time, and the code below prints "2" both times.

#!/usr/bin/ruby1.9.1
 
def funcA
   puts("1")
end
 
def funcB
   funcA()
end
 
def funcA
   puts("2")
end
 
funcA()
funcB()

I guess that depends on the compiler. DXL can be viewed as a compiled language, since it will be completely transformed to an intermediate format before running. If the compiler parses from top to bottom it would be only only logical the the code calls the last definition for a function. While this might lead to code that can be hard to understand, I might consider that as a feature, but it might not really go well together with forward references ... Regards, Mathias

Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

Re: Duplicate Functions
llandale - Thu Jul 07 10:14:35 EDT 2011

SystemAdmin - Wed Jul 06 10:15:05 EDT 2011

Complied languages should either flag that as an error or print "2nd" both times, depending on how lenient they are about redefinitions. Interpreted languages should print "2nd" both times. I'm a burgeoning Ruby nerd in my off time, and the code below prints "2" both times.

#!/usr/bin/ruby1.9.1
 
def funcA
   puts("1")
end
 
def funcB
   funcA()
end
 
def funcA
   puts("2")
end
 
funcA()
funcB()

Seems to me we did this years ago (with punch cards):

int  iValue = 0
void  ModIVal() {modify iValue}
int   GetIVal() { return iValue}
int  iValue = 0      // dummy variable to protect the real iValue above


This protects critical variable iValue. Code that follows which unethically dealt with iValue directly would modify the dummy value, and who cares. You can retrieve the value with GetIVal() and modify it ethically and safely with ModIVal().

I would thus expect (in my ignorance) that your code would print "1" then "2".

You cannot do that with DXL. You can duplicate a function but not a variable "iValue already defined in this scope".

 

 

  • Louie

 

 

Re: Duplicate Functions
AlexTidmarsh - Mon Nov 24 18:21:46 EST 2014

Mathias Mamsch - Thu Jun 30 19:26:01 EDT 2011

That is not normal, but I noticed the same. A forward reference before and after the call will crash DOORS with an exception. I guess forward references are not properly implemented. If utterly needed, you could replace the forward declarations by a callback proxy like below. Nice thing about that is, you can change the function at runtime ...
 

// instead of forward declaring  func() use a virtual function 
int adFunc = 0; 
void call_func_proxy( void cb(int), int x ) { cb(x) }
void set_func (void cb(int) ) { adFunc = (addr_ cb) int }
void func (int x) { if (adFunc != 0) call_func_proxy(addr_ adFunc, x) }
 
// that function uses the not yet declared func() ...
void myLibraryFunction () { func 10 }
 
// declare the func we want to use late
void theRealFunc (int var) {
   print "This is the implementation of func that I would like to use:" var "\n"
}
// set it as the function we want to use now. May want to change that later. 
set_func(theRealFunc) 
 
myLibraryFunction ()

 


Regards, Mathias

 

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

 

I was intrigued by this, since I noted that whilst you can declare a C-style function pointer in DXL, the Interpreter doesn't allow you to call it.

So having experimented with your code, I have discovered one small problem:  It doesn't work if the routine you want to alias is of the pattern "void(f)(void)".  (Obviously after rewriting your example to adapt to the new function type).

You get an internal error the moment you try to assign the function address to the integer storage.  Presumably this is because the DXL interpreter no-longer understands what is meant by adFunc = (addr_ function) int  if the function has no arguments or result.  It doesn't know if you meant it to be called or to simply get its address.  My suspicion is that it decides to call it, with disastrous results.

That said, if you don't mind "throwing away results", you could opt for your function's pattern to be "int(f)(void)".   This, for some bizarre reason, does not cause the interpreter to go ape when you do the adFunc = (addr_ function) int  part.  

To experiment with what was going wrong, I extracted the critical part that was causing the interpreter to blow up so I could easily experiment with the function patterns.  I provide this below, so you can quickly test what would work and what does not.

        int adFunc
        void SetF(int (f)(void))  { adFunc=(addr_ f) int }
        int Test(void){}
        SetF(Test)

The above works.

        int adFunc
        void SetF(void(f)(int))  { adFunc=(addr_ f) int }
        void Test(int){}
        SetF(Test)

The above also works.

        int adFunc
        void SetF(void(f)(void))  { adFunc=(addr_ f) int }
        void Test(void){}
        SetF(Test)

The above blows up the interpreter!

 

Re: Duplicate Functions
Mathias Mamsch - Tue Nov 25 04:29:48 EST 2014

AlexTidmarsh - Mon Nov 24 18:21:46 EST 2014

I was intrigued by this, since I noted that whilst you can declare a C-style function pointer in DXL, the Interpreter doesn't allow you to call it.

So having experimented with your code, I have discovered one small problem:  It doesn't work if the routine you want to alias is of the pattern "void(f)(void)".  (Obviously after rewriting your example to adapt to the new function type).

You get an internal error the moment you try to assign the function address to the integer storage.  Presumably this is because the DXL interpreter no-longer understands what is meant by adFunc = (addr_ function) int  if the function has no arguments or result.  It doesn't know if you meant it to be called or to simply get its address.  My suspicion is that it decides to call it, with disastrous results.

That said, if you don't mind "throwing away results", you could opt for your function's pattern to be "int(f)(void)".   This, for some bizarre reason, does not cause the interpreter to go ape when you do the adFunc = (addr_ function) int  part.  

To experiment with what was going wrong, I extracted the critical part that was causing the interpreter to blow up so I could easily experiment with the function patterns.  I provide this below, so you can quickly test what would work and what does not.

        int adFunc
        void SetF(int (f)(void))  { adFunc=(addr_ f) int }
        int Test(void){}
        SetF(Test)

The above works.

        int adFunc
        void SetF(void(f)(int))  { adFunc=(addr_ f) int }
        void Test(int){}
        SetF(Test)

The above also works.

        int adFunc
        void SetF(void(f)(void))  { adFunc=(addr_ f) int }
        void Test(void){}
        SetF(Test)

The above blows up the interpreter!

 

Mighty Magic Hal posted a way to get the address for void functions here:

https://www.ibm.com/developerworks/community/forums/html/topic?id=77777777-0000-0000-0000-000014541668&ps=25

Regards, Mathias